//package com.tianji.tjpromotion.service.impl;
//
//import com.tianji.common.exceptions.BizIllegalException;
//import com.tianji.common.exceptions.DbException;
//import com.tianji.common.utils.UserContext;
//import com.tianji.tjpromotion.domain.po.Coupon;
//import com.tianji.tjpromotion.domain.po.ExchangeCode;
//import com.tianji.tjpromotion.domain.po.UserCoupon;
//import com.tianji.tjpromotion.enums.ExchangeCodeStatus;
//import com.tianji.tjpromotion.mapper.CouponMapper;
//import com.tianji.tjpromotion.mapper.UserCouponMapper;
//import com.tianji.tjpromotion.service.IExchangeCodeService;
//import com.tianji.tjpromotion.service.IUserCouponService;
//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
//import com.tianji.tjpromotion.utils.CodeUtil;
//import com.tianji.tjpromotion.utils.RedisLock;
//import lombok.RequiredArgsConstructor;
//import org.redisson.api.RLock;
//import org.redisson.api.RedissonClient;
//import org.springframework.aop.framework.AopContext;
//import org.springframework.boot.autoconfigure.cache.CacheProperties;
//import org.springframework.stereotype.Service;
//import org.springframework.transaction.annotation.Transactional;
//
//import java.time.LocalDateTime;
//import java.util.concurrent.TimeUnit;
//
///**
// * <p>
// * 用户领取优惠券的记录，是真正使用的优惠券信息 服务实现类
// * </p>
// *
// * @author yp
// * @since 2024-08-04
// */
//@Service
//@RequiredArgsConstructor
//public class UserCouponServiceImpl extends ServiceImpl<UserCouponMapper, UserCoupon> implements IUserCouponService {
//
//    private final CouponMapper couponMapper;
//    private final RedisLock redisLock;
//    private final IExchangeCodeService exchangeCodeService;
//
//    private final RedissonClient redissonClient;
//
//    @Override
//
//    public void receiveCoupon(Long id) {
//        //开启事务
//        //1.根据id 查询优惠卷
//        Coupon coupon = couponMapper.selectById(id);
//        if (coupon == null) {
//            throw new DbException("优惠卷不存在");
//        }
//
//        //2.判断发放的时间
//        LocalDateTime now = LocalDateTime.now();
//        if (now.isBefore(coupon.getIssueBeginTime()) || now.isAfter(coupon.getIssueEndTime())) {
//            throw new BizIllegalException("优惠卷不在领取的时间内");
//        }
//
//        //3.判断库存是否充足
//        if (coupon.getIssueNum() >= coupon.getTotalNum()) {
//            throw new BizIllegalException("优惠卷库存不足");
//        }
//        //4.判断是否超存当前的领取数目
//        Long userId = UserContext.getUser();
//        //toString()是new String ; intern（）是吧字符串放在穿池里面 ， 如果穿池里面由，就不会创建对象
////        synchronized (userId.toString().intern()) {
////            IUserCouponService proxy = (IUserCouponService)AopContext.currentProxy();
////            proxy.checkAndCreateUserCoupon(coupon, userId);
////        }
//
//
////        boolean b = redisLock.tryLock("coupon:receive:" + userId, 10, TimeUnit.SECONDS);
////        if(!b){
////            throw new BizIllegalException("操作太频繁");
////        }
////        try {
////            IUserCouponService proxy = (IUserCouponService)AopContext.currentProxy();
////            proxy.checkAndCreateUserCoupon(coupon, userId);
////        } finally {
////            redisLock.unlock("coupon:receive:" + userId);
////        }
//
//
//        //1.使用redis使用的分布式锁
//        RLock lock = redissonClient.getLock("coupon:receive:" + userId);
//
//        //redissonclient的分布式锁
//        //加锁
//        boolean b = lock.tryLock();
//        if(!b){
//            throw new BizIllegalException("请求太频繁");
//        }
//        try {
//            IUserCouponService proxy = (IUserCouponService) AopContext.currentProxy();
//            proxy.checkAndCreateUserCoupon(coupon, userId);
//        } finally {
//            lock.unlock();
//        }
//        //开启事务
//        //获得锁
//        //释放锁
//        //提交事务
//    }
//
//
//    /**
//     * 判断是否超出了每人领取的数量和生成用户卷
//     *
//     * @param coupon
//     */
//    @Transactional
//    public void checkAndCreateUserCoupon(Coupon coupon, Long userId) {
//        Integer count = lambdaQuery()
//                .eq(UserCoupon::getCouponId, coupon.getId())
//                .eq(UserCoupon::getUserId, userId)
//                .count();
//        if (coupon.getUserLimit() <= count) {
//            throw new BizIllegalException("领取人数超过一定的数量");
//        }
//        //5.优惠卷的数量加1
//        int rows = couponMapper.incrIssueNum(coupon.getId());
//        if (rows == 0) {
//            throw new DbException("优惠卷领取失败");
//        }
//
//        //6.生成用户卷
//        UserCoupon userCoupon = new UserCoupon();
//        userCoupon.setCouponId(coupon.getId());
//        userCoupon.setUserId(UserContext.getUser());
//        //封装优惠卷的使用期限
//        LocalDateTime termBeginTime = coupon.getTermBeginTime();
//        LocalDateTime termEndTime = coupon.getTermEndTime();
//        //如果是固定天数是没有termBeginTime和termEndTime
//        if (termBeginTime == null) {
//            termBeginTime = LocalDateTime.now();
//            termEndTime = termBeginTime.plusDays(coupon.getTermDays());
//        }
//        userCoupon.setTermBeginTime(termBeginTime);
//        userCoupon.setTermEndTime(termEndTime);
//        save(userCoupon);
//    }
//
//
//    /**
//     * 兑换兑换码 Transactional =》 交给了Spring管理事务 => 通过AOP来实现 => 通过Aop动态代理来调用
//     *
//     * @param code
//     */
//    @Override
//    @Transactional
//    public void exchangeCoupon(String code) {
//        //1.解析兑换码
//        long id = CodeUtil.parseCode(code);
//        //2.查询兑换码
//        ExchangeCode exchangeCode = exchangeCodeService.getById(id);
//        //3.是否存在
//        if (exchangeCode == null) {
//            throw new DbException("兑换码不存在");
//        }
//        //4.是否已经兑换
//        if (exchangeCode.getStatus() == ExchangeCodeStatus.USED) {
//            throw new BizIllegalException("兑换码不能小重复兑换");
//        }
//
//        //5.判断是否过期
//        LocalDateTime now = LocalDateTime.now();
//        if (now.isAfter(exchangeCode.getExpiredTime())) {
//            throw new BizIllegalException("兑换码已经过期");
//        }
//        //6.是否超出限领的数量
//        //7.优惠卷的领取数量加1
//        //生成用户劵
//        Long userId = UserContext.getUser();
//        Coupon coupon = couponMapper.selectById(exchangeCode.getExchangeTargetId());
//        checkAndCreateUserCoupon(coupon, userId);
//        //9.更新兑换码状态
//
//        exchangeCode.setStatus(ExchangeCodeStatus.USED);
//        exchangeCode.setUserId(userId);
//        exchangeCodeService.updateById(exchangeCode);
//    }
//}
